home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Snippets / Dim Text 3.0 / Dim_text_3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-03  |  8.9 KB  |  334 lines  |  [TEXT/CWIE]

  1. #define        STRICT_WINDOWS    1
  2. #include <Memory.h>
  3. #include <Palettes.h>
  4. #include <Dialogs.h>
  5. #include <Gestalt.h>
  6. #include "Dim_text_3.h"
  7.  
  8. static pascal void Dim_text_proc( short byteCnt, Ptr textAddr,
  9.         Point numerPt, Point denomPt );
  10. static void Gray_frame_rect( Rect *bounds );
  11. static pascal void Gray_frame_draw_proc( short depth, short dev_flags,
  12.     GDHandle dev, Rect *bounds );
  13.  
  14. /*    ---------------------------------------------------------------------
  15.     Dim_text            This is a group of routines for dimming text
  16.                         items in dialogs.  As is, it assumes that you are
  17.                         not using the dialog's refCon for anything else.
  18.     
  19.     This code can be used freely.  I ask that you tell me about any
  20.     improvements that you think of.
  21.     
  22.     James W. Walker        December 4, 1995
  23.     JWWalker@kagi.com
  24.     76367.2271@compuserve.com
  25.     ---------------------------------------------------------------------
  26. */
  27.  
  28. typedef struct Dim_list_el {
  29.     struct Dim_list_el    *next;
  30.     Rect                bounds;
  31.     short                item_num;
  32.     Boolean                editable;
  33. } Dim_list_el;
  34.  
  35. typedef struct {
  36.     Dim_list_el        *dim_list;
  37.     ModalFilterUPP    User_filter;
  38. } Dim_data;
  39.  
  40.  
  41. /*    ---------------------------------------------------------------------
  42.     Get_dim_data        Macro to get the list head.
  43.     Set_dim_data        Macro to store the list head.
  44.     
  45.                         Just used to encapsulate the use of the refCon,
  46.                         so that if you need to store the list head
  47.                         somewhere else you will only need to change this.
  48.     ---------------------------------------------------------------------
  49. */
  50. #ifdef __cplusplus
  51.     inline Dim_data * Get_dim_data( DialogRef dp )
  52.     {
  53.         return (Dim_data *) GetWRefCon( GetDialogWindow( dp ) );
  54.     }
  55.     
  56.     inline void Set_dim_data( DialogRef dp, Dim_data *dim_head )
  57.     {
  58.         SetWRefCon( GetDialogWindow( dp ), (long) dim_head );
  59.     }
  60. #else
  61.     #define    Get_dim_data( dp )    ((Dim_data *) GetWRefCon( GetDialogWindow( dp ) ))
  62.     #define    Set_dim_data( dp, dim_head )    SetWRefCon( GetDialogWindow( dp ), (long) dim_head )
  63. #endif
  64.  
  65. /*    ---------------------------------------------------------------------
  66.     SetDialogKeyboardFocusItem        This is the one part of my code that
  67.                                     is not quite compatible with using the
  68.                                     STRICT_WINDOWS flag for Copland-readiness.
  69.     In non-STRICT_WINDOWS terms what it does is
  70.     ((DialogPeek) dialog)->editField = item-1;
  71.     ---------------------------------------------------------------------
  72. */
  73. #ifdef __cplusplus
  74.     inline void    SetDialogKeyboardFocusItem( DialogRef dialog, short item )
  75.     {
  76.         *(SInt16 *) (((UInt8 *) dialog) + 164) = item - 1;
  77.     }
  78. #else
  79.     #define    SetDialogKeyboardFocusItem(dialog, item)    do{*(SInt16 *) (((UInt8 *) dialog) + 164) = item - 1;} while (false);
  80. #endif
  81.  
  82. /*    ---------------------------------------------------------------------
  83.     Init_dimmer        Set up a dialog for dimming text.  Call it once, soon
  84.                     after creating the dialog.
  85.     
  86.     Inputs:
  87.         DialogRef dp            The dialog in which we will dim text.
  88.         
  89.         ModalFilterUPP User_filter
  90.                                 What you would have used as a modal filter
  91.                                 routine if you were not using Dim_filter_proc.
  92.                                 You can pass NULL, and then Dim_filter_proc
  93.                                 will call the standard filter.
  94.     ---------------------------------------------------------------------
  95. */
  96. void Init_dimmer( DialogRef dp, ModalFilterUPP User_filter )
  97. {
  98.     Dim_data    *dim_head;
  99.     
  100.     dim_head = (Dim_data *) NewPtrClear( sizeof(Dim_data) );
  101.     if (dim_head)
  102.     {
  103.         if (User_filter == NULL)
  104.             GetStdFilterProc( &dim_head->User_filter );
  105.         else
  106.             dim_head->User_filter = User_filter;
  107.         // Store the pointer where we can find it later
  108.         Set_dim_data( dp, dim_head );
  109.     }
  110. }
  111.  
  112. /*    ---------------------------------------------------------------------
  113.     Dim_filter_proc        Dialog filter that you pass to ModalDialog.
  114.     ---------------------------------------------------------------------
  115. */
  116. pascal Boolean Dim_filter_proc( DialogRef theDialog, EventRecord *theEvent, short *itemHit )
  117. {
  118.     Boolean        result = false;
  119.     Dim_data    *dim_head;
  120.     Dim_list_el    *this_el;
  121.     RgnHandle    boundsRgn;
  122.     
  123.     dim_head = Get_dim_data( theDialog );
  124.     if (dim_head != NULL)
  125.     {
  126.         if ( (theEvent->what == updateEvt)
  127.             && (theDialog == (DialogRef) theEvent->message) )
  128.         {
  129.             boundsRgn = NewRgn();
  130.             for (this_el = dim_head->dim_list; this_el != NULL; this_el = this_el->next )
  131.             {
  132.                 if (this_el->editable)
  133.                 {
  134.                     Gray_frame_rect( &this_el->bounds );
  135.                 }
  136.                 RectRgn( boundsRgn, &this_el->bounds );
  137.                 TextMode( grayishTextOr );
  138.                 UpdateDialog( theDialog, boundsRgn );
  139.                 TextMode( srcOr );
  140.                 ValidRect( &this_el->bounds );
  141.             }
  142.             DisposeRgn( boundsRgn );
  143.         }
  144.         
  145.         result = CallModalFilterProc( dim_head->User_filter, theDialog, theEvent, itemHit );
  146.     }
  147.     
  148.     return result;
  149. }
  150.  
  151. /*    ---------------------------------------------------------------------
  152.     Dispose_dimmer        Called once after you are through with a dialog.
  153.     ---------------------------------------------------------------------
  154. */
  155. void Dispose_dimmer( DialogRef dp )
  156. {
  157.     Dim_data    *dim_head;
  158.     Dim_list_el    *this_el, *next;
  159.     
  160.     dim_head = Get_dim_data(dp);
  161.     if (dim_head)
  162.     {
  163.         this_el = dim_head->dim_list;
  164.         while (this_el != NULL)
  165.         {
  166.             EraseRect( &this_el->bounds );
  167.             InvalRect( &this_el->bounds );
  168.             next = this_el->next;
  169.             DisposePtr( (Ptr) this_el );
  170.             this_el = next;
  171.         }
  172.         
  173.         DisposePtr( (Ptr) dim_head );
  174.     }
  175. }
  176.  
  177. /*    ---------------------------------------------------------------------
  178.     Dim_text        Set the dimming state of a text item.
  179.     ---------------------------------------------------------------------
  180. */
  181. void Dim_text( DialogRef dp, short item, Boolean dim )
  182. {
  183.     Dim_data    *dim_head;
  184.     Dim_list_el    *dimmable, *predecessor;
  185.     Rect        iRect;
  186.     Handle        iHandle;
  187.     short        iType;
  188.     short        disable_flag;
  189.     
  190.     dim_head = Get_dim_data(dp);
  191.     if (dim_head != NULL)
  192.     {
  193.         GetDialogItem( dp, item, &iType, &iHandle, &iRect );
  194.         disable_flag = iType & itemDisable;
  195.  
  196.         // Try to find the right item number in the list.
  197.         dimmable = dim_head->dim_list;
  198.         while ( (dimmable != NULL) && (dimmable->item_num != item) )
  199.         {
  200.             dimmable = dimmable->next;
  201.         }
  202.  
  203.         if ( (dimmable == NULL) && dim )    // if it should be and isn't, dim it
  204.         {
  205.             dimmable = (Dim_list_el *) 
  206.                 NewPtrClear( sizeof(Dim_list_el) );
  207.             if (dimmable)
  208.             {
  209.                 dimmable->next = dim_head->dim_list;
  210.                 dim_head->dim_list = dimmable;
  211.                 dimmable->item_num = item;
  212.                 dimmable->editable = (iType & editText) != 0;
  213.                 dimmable->bounds = iRect;
  214.                 if (dimmable->editable)
  215.                 {
  216.                     InsetRect( &dimmable->bounds, -3, -3 );
  217.                     /*
  218.                         To dim an editable text item, we need to turn it
  219.                         into a static text item, and also take some care
  220.                         that it is not showing the insertion point or a
  221.                         selection range.
  222.                     */
  223.                     if (item == GetDialogKeyboardFocusItem( dp ) )
  224.                     {
  225.                         SelectDialogItemText( dp, item, 0, 0 );
  226.                     }
  227.                     SetDialogItem( dp, item, statText | disable_flag,
  228.                         iHandle, &iRect );
  229.                     if (item == GetDialogKeyboardFocusItem( dp ) )
  230.                         SetDialogKeyboardFocusItem( dp, 0 );
  231.                     InvalRect( &dimmable->bounds );
  232.                 }
  233.                 else
  234.                 {
  235.                     InvalRect( &iRect );
  236.                 }
  237.             }
  238.         }
  239.         else if ( (dimmable != NULL) && !dim )    // undim it
  240.         {
  241.             // Remove it from the list
  242.             if (dim_head->dim_list == dimmable)
  243.             {
  244.                 dim_head->dim_list = dimmable->next;
  245.             }
  246.             else
  247.             {
  248.                 predecessor = dim_head->dim_list;
  249.                 while (predecessor->next != dimmable)
  250.                 {
  251.                     predecessor = predecessor->next;
  252.                 }
  253.                 predecessor->next = dimmable->next;
  254.             }
  255.             
  256.             if (dimmable->editable)
  257.             {
  258.                 SetDialogItem( dp, item, editText | disable_flag,
  259.                     iHandle, &iRect );
  260.                 SelectDialogItemText( dp, item, 0, 0 );
  261.                 EraseRect( &iRect );
  262.             }
  263.             InvalRect( &dimmable->bounds );
  264.             
  265.             // Delete the list element
  266.             DisposePtr( (Ptr) dimmable );
  267.         }
  268.     }
  269. }
  270.  
  271.  
  272.  
  273. /*    ---------------------------------------------------------------------
  274.     Gray_frame_draw_proc        DeviceLoop drawing procedure called
  275.                                 by Gray_frame_rect.
  276.     ---------------------------------------------------------------------
  277. */
  278. static pascal void Gray_frame_draw_proc( short depth, short /* dev_flags */,
  279.     GDHandle dev, Rect *bounds )
  280. {
  281.     RGBColor    fore_color, back_color, gray_color;
  282.     long        gray_pat[2];
  283.     
  284.     if (depth > 1)
  285.     {
  286.         GetForeColor( &fore_color );
  287.         GetBackColor( &back_color );
  288.         gray_color = fore_color;
  289.         GetGray( dev, &back_color, &gray_color );
  290.         RGBForeColor( &gray_color );
  291.     }
  292.     else
  293.     {
  294.         gray_pat[0] = gray_pat[1] = 0xAA55AA55L;
  295.         PenPat( (ConstPatternParam) gray_pat );
  296.     }
  297.     
  298.     FrameRect( bounds );
  299.     
  300.     if (depth > 1)
  301.     {
  302.         RGBForeColor( &fore_color );
  303.     }
  304.     else
  305.     {
  306.         PenNormal();
  307.     }
  308. }
  309.  
  310. /*    ---------------------------------------------------------------------
  311.     Gray_frame_rect                Draw a gray rectangle; true gray
  312.                                 if possible, dithered otherwise.
  313.     ---------------------------------------------------------------------
  314. */
  315. static void Gray_frame_rect( Rect *bounds )
  316. {
  317.     RgnHandle    save_clip, draw_rgn;
  318.     DeviceLoopDrawingUPP    Draw_UPP;
  319.     
  320.     PenNormal();
  321.     save_clip = NewRgn();
  322.     GetClip( save_clip );
  323.     draw_rgn = NewRgn();
  324.     RectRgn( draw_rgn, bounds );
  325.     SetClip( draw_rgn );
  326.     Draw_UPP = NewDeviceLoopDrawingProc( Gray_frame_draw_proc );
  327.     DeviceLoop( draw_rgn, Draw_UPP, (long) bounds, 0 );
  328.     DisposeRoutineDescriptor( Draw_UPP );
  329.     SetClip( save_clip );
  330.     DisposeRgn( draw_rgn );
  331.     DisposeRgn( save_clip );
  332.     PenNormal();
  333. }
  334.